<html><body><pre class="prettyprint">
        // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

        #ifndef UNITY_GLOBAL_ILLUMINATION_INCLUDED
        #define UNITY_GLOBAL_ILLUMINATION_INCLUDED
        
        // Functions sampling light environment data (lightmaps, light probes, reflection probes), which is then returned as the UnityGI struct.
        
        #include "UnityImageBasedLighting.cginc"
        #include "UnityStandardUtils.cginc"
        #include "UnityShadowLibrary.cginc"
        
        inline half3 <a name="DecodeDirectionalSpecularLightmap">DecodeDirectionalSpecularLightmap</a> (half3 color, half4 dirTex, half3 normalWorld, bool isRealtimeLightmap, fixed4 realtimeNormalTex, out UnityLight o_light)
        {
            o_light.color = color;
            o_light.dir = dirTex.xyz * 2 - 1;
            o_light.ndotl = 0; // Not use;
        
            // The length of the direction vector is the light's "directionality", i.e. 1 for all light coming from this direction,
            // lower values for more spread out, ambient light.
            half directionality = max(0.001, length(o_light.dir));
            o_light.dir /= directionality;
        
            #ifdef DYNAMICLIGHTMAP_ON
            if (isRealtimeLightmap)
            {
                // Realtime directional lightmaps' intensity needs to be divided by N.L
                // to get the incoming light intensity. Baked directional lightmaps are already
                // output like that (including the max() to prevent div by zero).
                half3 realtimeNormal = realtimeNormalTex.xyz * 2 - 1;
                o_light.color /= max(0.125, dot(realtimeNormal, o_light.dir));
            }
            #endif
        
            // Split light into the directional and ambient parts, according to the directionality factor.
            half3 ambient = o_light.color * (1 - directionality);
            o_light.color = o_light.color * directionality;
        
            // Technically this is incorrect, but helps hide jagged light edge at the object silhouettes and
            // makes normalmaps show up.
            ambient *= saturate(dot(normalWorld, o_light.dir));
            return ambient;
        }
        
        inline void <a name="ResetUnityLight">ResetUnityLight</a>(out UnityLight outLight)
        {
            outLight.color = half3(0, 0, 0);
            outLight.dir = half3(0, 1, 0); // Irrelevant direction, just not null
            outLight.ndotl = 0; // Not used
        }
        
        inline half3 <a name="SubtractMainLightWithRealtimeAttenuationFromLightmap">SubtractMainLightWithRealtimeAttenuationFromLightmap</a> (half3 lightmap, half attenuation, half4 bakedColorTex, half3 normalWorld)
        {
            // Let's try to make realtime shadows work on a surface, which already contains
            // baked lighting and shadowing from the main sun light.
            half3 shadowColor = unity_ShadowColor.rgb;
            half shadowStrength = _LightShadowData.x;
        
            // Summary:
            // 1) Calculate possible value in the shadow by subtracting estimated light contribution from the places occluded by realtime shadow:
            //      a) preserves other baked lights and light bounces
            //      b) eliminates shadows on the geometry facing away from the light
            // 2) Clamp against user defined ShadowColor.
            // 3) Pick original lightmap value, if it is the darkest one.
        
        
            // 1) Gives good estimate of illumination as if light would've been shadowed during the bake.
            //    Preserves bounce and other baked lights
            //    No shadows on the geometry facing away from the light
            half ndotl = LambertTerm (normalWorld, _WorldSpaceLightPos0.xyz);
            half3 estimatedLightContributionMaskedByInverseOfShadow = ndotl * (1- attenuation) * _LightColor0.rgb;
            half3 subtractedLightmap = lightmap - estimatedLightContributionMaskedByInverseOfShadow;
        
            // 2) Allows user to define overall ambient of the scene and control situation when realtime shadow becomes too dark.
            half3 realtimeShadow = max(subtractedLightmap, shadowColor);
            realtimeShadow = lerp(realtimeShadow, lightmap, shadowStrength);
        
            // 3) Pick darkest color
            return min(lightmap, realtimeShadow);
        }
        
        inline void <a name="ResetUnityGI">ResetUnityGI</a>(out UnityGI outGI)
        {
            ResetUnityLight(outGI.light);
            outGI.indirect.diffuse = 0;
            outGI.indirect.specular = 0;
        }
        
        inline UnityGI <a name="UnityGI_Base">UnityGI_Base</a>(UnityGIInput data, half occlusion, half3 normalWorld)
        {
            UnityGI o_gi;
            ResetUnityGI(o_gi);
        
            // Base pass with Lightmap support is responsible for handling ShadowMask / blending here for performance reason
            #if defined(HANDLE_SHADOWS_BLENDING_IN_GI)
                half bakedAtten = UnitySampleBakedOcclusion(data.lightmapUV.xy, data.worldPos);
                float zDist = dot(_WorldSpaceCameraPos - data.worldPos, UNITY_MATRIX_V[2].xyz);
                float fadeDist = UnityComputeShadowFadeDistance(data.worldPos, zDist);
                data.atten = UnityMixRealtimeAndBakedShadows(data.atten, bakedAtten, UnityComputeShadowFade(fadeDist));
            #endif
        
            o_gi.light = data.light;
            o_gi.light.color *= data.atten;
        
            #if UNITY_SHOULD_SAMPLE_SH
                o_gi.indirect.diffuse = ShadeSHPerPixel(normalWorld, data.ambient, data.worldPos);
            #endif
        
            #if defined(LIGHTMAP_ON)
                // Baked lightmaps
                half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
                half3 bakedColor = DecodeLightmap(bakedColorTex);
        
                #ifdef DIRLIGHTMAP_COMBINED
                    fixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER (unity_LightmapInd, unity_Lightmap, data.lightmapUV.xy);
                    o_gi.indirect.diffuse += DecodeDirectionalLightmap (bakedColor, bakedDirTex, normalWorld);
        
                    #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
                        ResetUnityLight(o_gi.light);
                        o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap (o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);
                    #endif
        
                #else // not directional lightmap
                    o_gi.indirect.diffuse += bakedColor;
        
                    #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
                        ResetUnityLight(o_gi.light);
                        o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap(o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);
                    #endif
        
                #endif
            #endif
        
            #ifdef DYNAMICLIGHTMAP_ON
                // Dynamic lightmaps
                fixed4 realtimeColorTex = UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, data.lightmapUV.zw);
                half3 realtimeColor = DecodeRealtimeLightmap (realtimeColorTex);
        
                #ifdef DIRLIGHTMAP_COMBINED
                    half4 realtimeDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, data.lightmapUV.zw);
                    o_gi.indirect.diffuse += DecodeDirectionalLightmap (realtimeColor, realtimeDirTex, normalWorld);
                #else
                    o_gi.indirect.diffuse += realtimeColor;
                #endif
            #endif
        
            o_gi.indirect.diffuse *= occlusion;
            return o_gi;
        }
        
        
        inline half3<a name="UnityGI_IndirectSpecular">UnityGI_IndirectSpecular</a>(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn)
        {
            half3 specular;
        
            #ifdef UNITY_SPECCUBE_BOX_PROJECTION
                // we will tweak reflUVW in glossIn directly (as we pass it to Unity_GlossyEnvironment twice for probe0 and probe1), so keep original to pass into BoxProjectedCubemapDirection
                half3 originalReflUVW = <a href="UnityImageBasedLighting.html#Unity_GlossyEnvironmentData.reflUVW">glossIn.reflUVW</a>;
                <a href="UnityImageBasedLighting.html#Unity_GlossyEnvironmentData.reflUVW">glossIn.reflUVW</a> = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
            #endif
        
            #ifdef _GLOSSYREFLECTIONS_OFF
                specular = unity_IndirectSpecColor.rgb;
            #else
                half3 env0 = Unity_GlossyEnvironment (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);
                #ifdef UNITY_SPECCUBE_BLENDING
                    const float kBlendFactor = 0.99999;
                    float blendLerp = data.boxMin[0].w;
                    UNITY_BRANCH
                    if (blendLerp < kBlendFactor)
                    {
                        #ifdef UNITY_SPECCUBE_BOX_PROJECTION
                            glossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);
                        #endif
        
                        half3 env1 = Unity_GlossyEnvironment (UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1,unity_SpecCube0), data.probeHDR[1], glossIn);
                        specular = lerp(env1, env0, blendLerp);
                    }
                    else
                    {
                        specular = env0;
                    }
                #else
                    specular = env0;
                #endif
            #endif
        
            return specular * occlusion;
        }
        
        // Deprecated old prototype but can't be move to Deprecated.cginc file due to order dependency
        inline half3 UnityGI_IndirectSpecular(UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)
        {
            // normalWorld is not used
            return UnityGI_IndirectSpecular(data, occlusion, glossIn);
        }
        
        inline UnityGI <a name="UnityGlobalIllumination">UnityGlobalIllumination</a> (UnityGIInput data, half occlusion, half3 normalWorld)
        {
            return UnityGI_Base(data, occlusion, normalWorld);
        }
        
        inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)
        {
            UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld);
            o_gi.indirect.specular = UnityGI_IndirectSpecular(data, occlusion, glossIn);
            return o_gi;
        }
        
        //
        // Old UnityGlobalIllumination signatures. Kept only for backward compatibility and will be removed soon
        //
        
        inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half smoothness, half3 normalWorld, bool reflections)
        {
            if(reflections)
            {
                Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(smoothness, data.worldViewDir, normalWorld, float3(0, 0, 0));
                return UnityGlobalIllumination(data, occlusion, normalWorld, g);
            }
            else
            {
                return UnityGlobalIllumination(data, occlusion, normalWorld);
            }
        }
        inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half smoothness, half3 normalWorld)
        {
        #if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
            // No need to sample reflection probes during deferred G-buffer pass
            bool sampleReflections = false;
        #else
            bool sampleReflections = true;
        #endif
            return UnityGlobalIllumination (data, occlusion, smoothness, normalWorld, sampleReflections);
        }
        
        
        #endif
</pre>
<script src="https://xibanya.github.io/ShaderTutorials/CGIncludes/code-prettify/loader/run_prettify.js?skin=vscode"></script>
<script src="https://xibanya.github.io/ShaderTutorials/CGIncludes/Data/link_definitions.js"></script>
</body></html>